package client.logic.chat;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;

import packets.Packet;
import packets.server.Certificate;

import client.gui.frmChatFrame;
import client.logic.Controller;
import client.logic.Facade;
import encription.SecurityHandler;

/**
 *	Class to start a chat session with a foreign user
 */
public class ChatStarter extends Thread implements Chatter{

	private Socket _socket;
	private ChatSender _chatSender;
	private ChatReciever _chatReciever;
	private InetSocketAddress _friendAddr;
	private String _friendName;
	private PrivateKey _decryptionKey;
	private PublicKey _encryptionKey;
	private Certificate _cf;
	private Controller _controller;

	/**
	 * Creates an instance of ChatStarter
	 * @param adder address of the foreign client
	 * @param name name of the foreign client
	 * @param decryptionKey	key to decrypt received messages
	 * @param encryptionKey	key to encrypt sent messages
	 * @param cf certificate to send to the foreign client (so he can verify)
	 * @param controller
	 */
	public ChatStarter(InetSocketAddress adder, String name, PrivateKey decryptionKey,PublicKey encryptionKey, Certificate cf, Controller controller){
		_friendAddr = adder;
		_friendName = name;
		_decryptionKey = decryptionKey;
		_encryptionKey = encryptionKey;
		_cf = cf;
		_controller = controller;
	}

	/**
	 * starts the ChatStarter thread
	 */
	public void run(){
		try {
			Packet verifyPacket = _controller.verifyKey(_encryptionKey);
			if (verifyPacket.getType() != Packet.OK){
				throw new InvalidKeyException("CRL: not a valid key");
			}
			//System.out.println(_friendName +", " +_friendAddr.getAddress() + "," + _friendAddr.getPort());
			_socket = new Socket(_friendAddr.getAddress(), _friendAddr.getPort());	//connects with the foreign client
			if (_socket.isConnected() && _socket.isBound()){
				frmChatFrame chatFrame = new frmChatFrame(this , _friendName);		//starts a chat frame
				chatFrame.setVisible(true);

				_chatReciever = new ChatReciever(_socket , chatFrame, _decryptionKey);	//initiates the chat message receiver
				_chatReciever.start();
				_chatSender = new ChatSender(_socket , Facade.getInstance().getLoggedUser(), _encryptionKey);	//initiates the chat message sender
				_chatSender.init(_cf);																			//initializes the chat sender and sends the certificate to the foreign user
			}
		} catch (Exception e) {
			reset();				//dismiss the current chat session and lets the client to start new chat sessions
			SecurityHandler.catchException("initiating a chat", e, true);
			//e.printStackTrace();
		}
	}

	public void sendChatMessage(String message) {
		if (_chatSender!=null)
			_chatSender.sendMessage(message);
	}
	public void close(){
		if (_chatSender!=null)
			_chatSender.close();
		if (_chatReciever!=null)
			_chatReciever.close();
	}

	public void reset(){
		Facade.getInstance().resetChat();
	}
}
